﻿using System;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.CTS.HSG;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Lib.UnitTest
{
    [TestClass]
    public class ScriptEngineConfigurationTest
    {
        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return this.testContextInstance;
            }
            set
            {
                this.testContextInstance = value;
            }
        }

        [TestMethod]
        public void ValidatePropertiesAreNullAtConstruction()
        {
            ScriptEngineConfiguration config = new ScriptEngineConfiguration();
            Assert.IsNull(config.Instance);
            Assert.IsNull(config.Database);
            Assert.IsNull(config.FileName);
        }

        [TestMethod]
        public void ValidatePropertiesSetToFalseAtConstruction()
        {
            ScriptEngineConfiguration config = new ScriptEngineConfiguration();
            Assert.IsFalse(config.AgentAlertJob);
            Assert.IsFalse(config.AgentJobId);
            Assert.IsFalse(config.AgentNotify);
            Assert.IsFalse(config.AllowSystemObjects);
            Assert.IsFalse(config.AnsiFile);
            Assert.IsFalse(config.Bindings);
            Assert.IsFalse(config.ChangeTracking);
            Assert.IsFalse(config.DdlBodyOnly);
            Assert.IsFalse(config.DdlHeaderOnly);
            Assert.IsFalse(config.LoginSid);
            Assert.IsFalse(config.MailProfileAccounts);
            Assert.IsFalse(config.MailProfilePrincipals);
            Assert.IsFalse(config.ScriptData);
            Assert.IsFalse(config.ScriptDrops);
            Assert.IsFalse(config.PrefetchObjects);
            Assert.IsFalse(config.AppendToFile);
            Assert.IsFalse(config.ScriptDrops);

            //
            // Validate read-write properties' default values
            //
            Assert.IsFalse(config.Assemblies);
            Assert.IsFalse(config.OptimizerData);
            Assert.IsFalse(config.Statistics);
           
        }

        [TestMethod]
        public void ValidateStringPropertiesAreNullAtConstruction()
        {
            ScriptEngineConfiguration config = new ScriptEngineConfiguration();
            Assert.IsNull(config.Instance);
            Assert.IsNull(config.Database);
            Assert.IsNull(config.FileName);
        }

        [TestMethod]
        public void ValidatePropertiesSetToTrueAtConstruction()
        {
            ScriptEngineConfiguration config = new ScriptEngineConfiguration();
            Assert.IsTrue(config.AnsiPadding);
            Assert.IsTrue(config.ClusteredIndexes);
            Assert.IsTrue(config.ContinueScriptingOnError);
            Assert.IsTrue(config.ConvertUserDefinedDataTypesToBaseType);
            Assert.IsTrue(config.Default);
            Assert.IsTrue(config.DriAll);
            Assert.IsTrue(config.DriAllConstraints);
            Assert.IsTrue(config.DriAllKeys);
            Assert.IsTrue(config.DriChecks);
            Assert.IsTrue(config.DriClustered);
            Assert.IsTrue(config.DriDefaults);
            Assert.IsTrue(config.DriForeignKeys);
            Assert.IsTrue(config.DriIncludeSystemNames);
            Assert.IsTrue(config.DriIndexes);
            Assert.IsTrue(config.DriNonClustered);
            Assert.IsTrue(config.DriPrimaryKey);
            Assert.IsTrue(config.DriUniqueKeys);
            Assert.IsTrue(config.DriWithNoCheck);
            Assert.IsTrue(config.EnforceScriptingOptions);
            Assert.IsTrue(config.IncludeDatabaseContext);
            Assert.IsTrue(config.IncludeDatabaseRoleMemberships);
            Assert.IsTrue(config.IncludeHeaders);
            Assert.IsTrue(config.Indexes);
            Assert.IsTrue(config.CommandTerminator);
            Assert.IsTrue(config.ExecuteAs);
            Assert.IsTrue(config.FileGroup);
            Assert.IsTrue(config.FileStream);
            Assert.IsTrue(config.FileStreamColumn);
            Assert.IsTrue(config.Identities);
            Assert.IsTrue(config.IndexPartitioningSchemes);
            Assert.IsTrue(config.NonClusteredIndexes);
            Assert.IsTrue(config.TablePartitioningSchemes);
            Assert.IsTrue(config.Vardecimal);
            Assert.IsTrue(config.ViewColumns);
            Assert.IsTrue(config.XmlNamespaces);
            Assert.IsTrue(config.PrimaryObject);
            Assert.IsTrue(config.SchemaQualify);
            Assert.IsTrue(config.SchemaQualifyForeignKeysReferences);
            Assert.IsTrue(config.ScriptBatchTerminator);
            Assert.IsTrue(config.ScriptDataCompression);
            Assert.IsTrue(config.ScriptOwner);
            Assert.IsTrue(config.ScriptSchema);
            Assert.IsTrue(config.TimestampToBinary);
            Assert.IsTrue(config.ToFileOnly);
            Assert.IsTrue(config.Triggers);
            Assert.IsTrue(config.WithDependencies);
            Assert.IsTrue(config.XmlIndexes);
            Assert.IsTrue(config.CopyAllObjects);
            Assert.IsTrue(config.CopyAllLogins);
            Assert.IsTrue(config.Permissions);
            Assert.IsTrue(config.FullTextCatalogs);
            Assert.IsTrue(config.FullTextIndexes);
            Assert.IsTrue(config.FullTextStopLists);
            Assert.IsTrue(config.IncludeFullTextCatalogRootPath);
            Assert.IsTrue(config.Collation);
        }

        [TestMethod]
        public void ValidateProperties()
        {
            ScriptEngineConfiguration config = new ScriptEngineConfiguration();
            
            Assert.AreEqual<int>(
                1,
                config.BatchSize
                );

            Assert.AreEqual<Encoding>(
                Encoding.Unicode,
                config.Encoding
                );

            Assert.IsTrue(
                config.Statistics == config.OptimizerData
                );
        }

        [TestMethod]
        public void SetOptimizerProperty()
        {
            ScriptEngineConfiguration config = new ScriptEngineConfiguration();
            
            config.OptimizerData = true;
            
            Assert.AreEqual(
                config.OptimizerData,
                config.Statistics
                );

            config.OptimizerData = false;

            Assert.AreEqual(
                config.OptimizerData,
                config.Statistics
                );

        }

        [TestMethod]
        public void SetAssembliesProperty()
        {
            ScriptEngineConfiguration config = new ScriptEngineConfiguration();
            config.Assemblies = true;
            Assert.IsTrue(config.Assemblies);
            config.Assemblies = false;
            Assert.IsFalse(config.Assemblies);
        }

        [TestMethod]
        public void SetInstanceProperty()
        {
            ScriptEngineConfiguration config = new ScriptEngineConfiguration();
            string expectedInstance = "blah";
            config.Instance = expectedInstance;
            
            Assert.AreEqual<string>(
                expectedInstance,
                config.Instance
                );
        }

        [TestMethod]
        public void SetDatabaseProperty()
        {
            ScriptEngineConfiguration config = new ScriptEngineConfiguration();
            string expectedDatabase = "blah";
            config.Database = expectedDatabase;

            Assert.AreEqual<string>(
                expectedDatabase,
                config.Database
                );
        }

        [TestMethod]
        public void SetFileNameProperty()
        {
            ScriptEngineConfiguration config = new ScriptEngineConfiguration();
            string expectedFileName = "blah";
            config.FileName = expectedFileName;

            Assert.AreEqual<string>(
                expectedFileName,
                config.FileName
                );
        }

        [TestMethod]
        public void ValidateEnumsAtConstruction()
        {
            ScriptEngineConfiguration config = new ScriptEngineConfiguration();
            
            Assert.AreEqual(
                (SqlServerVersion)0,
                config.TargetServerVersion
                );

        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void ValidateConfigurationThrowsOnNullConfig()
        {
            ScriptEngineConfiguration config = null;
            ScriptEngineConfiguration.ValidateConfiguration(config);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void ValidateConfigurationThrowsOnNullInstance()
        {
            ScriptEngineConfiguration config = new ScriptEngineConfiguration();
            ScriptEngineConfiguration.ValidateConfiguration(config);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void ValidateConfigurationThrowsOnNullDatabase()
        {
            ScriptEngineConfiguration config = new ScriptEngineConfiguration();
            ScriptEngineConfiguration.ValidateConfiguration(config);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void ValidateConfigurationThrowsOnNullFileName()
        {
            ScriptEngineConfiguration config = new ScriptEngineConfiguration();
            ScriptEngineConfiguration.ValidateConfiguration(config);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void ValidateConfigurationThrowsOnEmptyInstance()
        {
            ScriptEngineConfiguration config = new ScriptEngineConfiguration();
            config.Instance = string.Empty;
            ScriptEngineConfiguration.ValidateConfiguration(config);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void ValidateConfigurationThrowsOnEmptyDatabase()
        {
            ScriptEngineConfiguration config = new ScriptEngineConfiguration();
            config.Instance = "blah";
            config.Database = string.Empty;
            ScriptEngineConfiguration.ValidateConfiguration(config);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void ValidateConfigurationThrowsOnNullEmptyFileName()
        {
            ScriptEngineConfiguration config = new ScriptEngineConfiguration();
            config.Instance = "blah";
            config.Database = "blah";
            config.FileName = string.Empty;
            ScriptEngineConfiguration.ValidateConfiguration(config);
        }

        [TestMethod]
        [ExpectedException(typeof(DirectoryNotFoundException))]
        public void ValidateConfigurationThrowsOnNonExistentDirectory()
        {
            ScriptEngineConfiguration config = new ScriptEngineConfiguration();
            config.Instance = "blah";
            config.Database = "blah";
            config.FileName = "c:\\blahblahblah\\test.sql";
            ScriptEngineConfiguration.ValidateConfiguration(config);
        }

        [TestMethod]
        public void SpecifyFileNameWithoutDirectory()
        {
            ScriptEngineConfiguration config = new ScriptEngineConfiguration();
            config.Instance = "blah";
            config.Database = "blah";
            config.FileName = "test.sql";
            ScriptEngineConfiguration.ValidateConfiguration(config);
        }
    }
}
